﻿using NUnit.Framework;

namespace GlobalStringFormatter.Tests
{
    public class Currency {}
    public class USD : Currency {}
    public class Euro : Currency {}

    [TestFixture]
    public class GStringTests
    {
        [Test]
        public void TestEmptyConstructor()
        {
            var gString1 = new GString<USD, double>();
            gString1.Value = 400.23;

            Assert.AreEqual(400.23, gString1.Value);
            Assert.AreEqual(0, gString1.Formatters.GetFormatters().Count);

            gString1.Value = 20330.98;
            Assert.AreEqual(20330.98, gString1.Value);

            var gString2 = new GString<USD, double>();
            gString2.Value = 32;

            Assert.AreEqual(32, gString2.Value);
            Assert.AreNotEqual(0, gString2.Value);

            gString2.Value = -300;
            Assert.AreEqual(-300, gString2.Value);
            Assert.IsTrue(-300 == gString2.Value);

            gString2.Value += 3;
            Assert.IsTrue(-297 == gString2.Value);
        }

        [Test]
        public void TestValueConstructor()
        {
            var gString1 = new GString<Euro, string>("http://www.nytimes.com/2011/01/23/magazine/23FOB-Q4-t.html?ref=magazine");
            Assert.AreEqual("http://www.nytimes.com/2011/01/23/magazine/23FOB-Q4-t.html?ref=magazine", gString1.Value);
            
            gString1.Value = "";
            Assert.AreEqual(string.Empty, gString1.Value);
        }

        [Test]
        public void TestValueFormatterSystemConstructor()
        {
            var system = new FormatterSystem<int> { Default = v => v.ToString() };
            system.Add(new Formatter<int>(v => v == 10, v => (v+1).ToString()));

            var gString = new GString<Euro, int>(3, system);
            Assert.AreEqual(3, gString.Value);
            Assert.AreEqual(system, gString.Formatters);
        }

        [Test]
        public void TestCopyConstructor()
        {
            var gString1 = new GString<USD, string>("abcdefg");
            var gString2 = new GString<USD, string>(gString1);

            Assert.AreNotEqual(gString1, gString2);
            Assert.AreEqual(gString1.Value, gString2.Value);
        }

        [Test]
        public void TestObjectAssignment()
        {
            var gString1 = new GString<USD, string>("abcdefg");
            var gString2 = gString1;

            Assert.AreEqual(gString1, gString2);

            Assert.AreEqual("abcdefg", gString1.Value);
            Assert.AreEqual("abcdefg", gString2.Value);

            gString1.Value = "abc";

            Assert.AreEqual("abc", gString1.Value);
            Assert.AreEqual("abc", gString2.Value);
        }

        [Test]
        public void TestFormatterAssignment()
        {
            var gString1 = new GString<Euro, double>(3808.84);
            gString1.Formatters.Add(v => v < 1000, v => string.Format("{0:C} E", v));
            gString1.Formatters.Add(v => v >= 1000 && v < 1000000, v => string.Format("{0:C}k E", v / 1000));
            gString1.Formatters.Add(v => v >= 1000000, v => string.Format("{0:C}m E", v / 1000000));

            Assert.AreEqual("$3.81k E", gString1.ToString());

            var gString2 = new GString<Euro, double>();
            gString2.Value = 3808.84;
            gString2.Formatters = gString1.Formatters;

            Assert.AreEqual("$3.81k E", gString2.ToString());

            var gString3 = new GString<USD, double>();
            gString3.Value = 3808.84;
            gString3.Formatters = gString2.Formatters;

            Assert.AreEqual("$3.81k E", gString3.ToString());
        }

        [Test]
        public void TestToString()
        {
            var gString = new GString<USD, double>(32.03);
            gString.Formatters.Add(v => (v < 1000 && v >= 0), v => string.Format("{0:C}", v));
            gString.Formatters.Add(v => v >= 1000 && v < 1000000, v => string.Format("{0:C}k", v / 1000));
            gString.Formatters.Add(v => v >= 1000000, v => string.Format("{0:C}m", v / 1000000));

            Assert.AreEqual("$32.03", gString.ToString());

            gString.Value = 1050.48;
            Assert.AreEqual("$1.05k", gString.ToString());

            gString.Value = 1315002.03;
            Assert.AreEqual("$1.32m", gString.ToString());
            Assert.AreEqual("Cash: $1.32m", string.Format("Cash: {0}", gString));

            gString.Value = 0;
            Assert.AreEqual("$0.00", gString.ToString());

            gString.Value = -5.05;
            Assert.AreEqual(string.Empty, gString.ToString());

            gString.Formatters.Default = v => v.ToString();
            Assert.AreEqual("-5.05", gString.ToString());
        }

    }
}
